/**
 * Copyright [2010] Delta Air Lines, Inc. All Rights Reserved Access,
 * Modification, or Use Prohibited Without Express Permission of Delta Air
 * Lines.
 */
package com.delta.rafg.core.config.impl;


import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Hashtable;
import java.util.Map;
import java.util.Properties;

import com.delta.rafg.core.database.DataHandlerOptions;
import com.delta.rafg.core.database.IDataHandler.POLL_STYLE;
import com.delta.rafg.core.database.impl.ADataHandler;
import com.delta.rafg.core.exception.RAFGException;
import com.delta.rafg.core.log.RAFGLogger;


/**
 * @author RAFG Development Team (D9127520)
 */
public class ConfigDataHandlerImpl extends ADataHandler {

    /**
     * Holds the value of serialVersionUID property.
     */
    private static final long serialVersionUID = 6485618194001579427L;

    /**
     * Holds the value of CONFIG_DB_TABLE property.
     */
    private static final String CONFIG_DB_TABLE = "AXIS.AXIS_CONFIG";

    /**
     * Holds the value of lastModifiedTs property.
     */
    private java.sql.Timestamp lastModifiedTs = null;

	private String pollFrequency = "1"; //once a minute
	private POLL_STYLE pollStyle = POLL_STYLE.INTERVAL;

    /**
     * Holds the value of configSettingsModifiedMap property.
     */
    private final Map<String, java.sql.Timestamp> configSettingsModifiedMap =
        new Hashtable<String, java.sql.Timestamp>();

    /**
     * Holds the value of driverClassName property.
     */
    private final String driverClassName = "oracle.jdbc.driver.OracleDriver";

    /**
     * @return properties of all configuration items in database.
     * @throws RAFGException RAFGException
     */
    public final Properties getAllProps() throws RAFGException {

        final Properties dbProps = new Properties();
        Statement stmt = null;
        try {
            final Connection conn = getConnection();
            stmt = conn.createStatement();
            final ResultSet rs =
                stmt.executeQuery("SELECT name, value, modified FROM "
                    + CONFIG_DB_TABLE + " ORDER BY name");
            while (rs.next()) {
                final String name = rs.getString("name");
                String value = rs.getString("value");
                final java.sql.Timestamp modified = rs.getTimestamp("modified");
                if (name != null && name.length() > 0) {
                    if (value == null) {
                        value = "";
                    }
                    dbProps.setProperty(name, value);
                    configSettingsModifiedMap.put(name, modified);
                    if (lastModifiedTs == null
                        || lastModifiedTs.before(modified)) {
                        lastModifiedTs = modified;
                    }
                }
            }
        } catch (final SQLException e) {
            throw new RAFGException(e);
            //RAFGLogger.error("Failed to connect to ConfigSettings central database: " + e.getMessage(), null, null);
        } finally {
            if (stmt != null) {
                try {
                    stmt.close();
                } catch (final SQLException e) {
                    throw new RAFGException(e);
                }
            }
        }
        return dbProps;
    }

    /**
     * @return Any configuration properties that have changed since the last
     *         time this method has been called.
     * @throws RAFGException RAFGException
     */
    public final Properties getChangedProps() throws RAFGException {

        final Properties dbProps = new Properties();
        Statement stmt = null;
        try {
            final Connection conn = getConnection();
            stmt = conn.createStatement();
            final ResultSet rs =
                stmt.executeQuery("SELECT name, value, modified FROM "
                    + CONFIG_DB_TABLE + " ORDER BY modified DESC");
            while (rs.next()) {
                final String name = rs.getString("name");
                String value = rs.getString("value");
                final java.sql.Timestamp modified = rs.getTimestamp("modified");
                if (name != null && name.length() > 0) {
                    if (value == null) {
                        value = "";
                    }
                    if (configSettingsModifiedMap.get(name) == null
                        || !configSettingsModifiedMap.get(name)
                            .equals(modified)) {
                        dbProps.setProperty(name, value);
                        configSettingsModifiedMap.put(name, modified);
                        if (lastModifiedTs.before(modified)) {
                            lastModifiedTs = modified;
                        }
                    }
                }
            }
        } catch (final SQLException e) {
            throw new RAFGException(e);
        } finally {
            if (stmt != null) {
                try {
                    stmt.close();
                } catch (final SQLException e) {
                    throw new RAFGException(e);
                }
            }
        }
        return dbProps;
    }

    /**
     * @return true/false if the configuration database content has changed
     * @throws RAFGException RAFGException
     */
    public final boolean hasConfigChanged() throws RAFGException {

        if (lastModifiedTs == null) { return true; }
        boolean bReturn = false;
        Statement stmt = null;
        try {
            final Connection conn = getConnection();
            stmt = conn.createStatement();
            final ResultSet rs =
                stmt.executeQuery("SELECT MAX(modified) FROM "
                    + CONFIG_DB_TABLE);
            if (rs.next()) {
                final java.sql.Timestamp modifiedTs =
                    rs.getTimestamp("modified");
                if (lastModifiedTs.before(modifiedTs)) {
                    bReturn = true;
                }
            }
        } catch (final SQLException e) {
            throw new RAFGException(e);
        } finally {
            if (stmt != null) {
                try {
                    stmt.close();
                } catch (final SQLException e) {
                    throw new RAFGException(e);
                }
            }
        }
        return bReturn;
    }

    /**
     * This method does used to initialize DataHandlerOptions
     * @param options
     * @throws RAFGException
     * @see DataHandlerOptions
     */
    @Override
    public void initialize(final DataHandlerOptions options)
        throws RAFGException {

        if (options.getDriverClassName() == null) {
            options.setDriverClassName(driverClassName);
        }
        super.initialize(options);
    }
    // /**
    // *
    // */
    // private Connection sqlConnection = null;
    //
    // @Override
    // public Connection getConnection() throws RAFGException {
    // try {
    // Connection conn;
    // if (getDataSource() == null) {
    // if (sqlConnection == null) {
    // Class.forName(driverClassName);
    // sqlConnection = DriverManager.getConnection(
    // getDataHandlerOptions().getConnectionUrl(),
    // getDataHandlerOptions().getUsername(),
    // getDataHandlerOptions().getPassword());
    // }
    // conn = sqlConnection;
    // } else {
    // conn = getDataSource().getConnection();
    // }
    // return conn;
    // } catch (java.sql.SQLException e) {
    // throw new RAFGException(e);
    // } catch (ClassNotFoundException e) {
    // throw new RAFGException(e);
    // }
    // }
    //
    // @Override
    // public void closeConnection() {
    // try {
    // sqlConnection.close();
    // } catch (SQLException e) {
    // }
    // sqlConnection = null;
    // }
    //
    // @Override
    // public void initialize(DataHandlerOptions options) throws RAFGException {
    // super.initialize(options);
    // }

	@Override
	public POLL_STYLE getPollStyle() {
		return pollStyle;
	}

	@Override
	public String getPollFrequency() {
		// TODO Auto-generated method stub
		return pollFrequency;
	}
}
